package com.ophiux.utils.parser.xml;

import java.util.ArrayList;
import java.util.List;
import java.util.SortedMap;

import org.w3c.dom.Element;

import com.ophiux.utils.exception.OphiuxApiException;
import com.ophiux.utils.parser.EntityConverter;
import com.ophiux.utils.parser.IConvert;
import com.ophiux.utils.parser.Reader;
import com.ophiux.utils.parser.Writer;
import com.ophiux.utils.common.XMLUtil;

public class XmlConverter implements IConvert {

	@Override
	public <T> T toEntity(Class<T> clzz, String dataSource) throws OphiuxApiException {
		Element rootElement = XMLUtil.getDocmentElement(dataSource);
		return buildEntityByXML(clzz, rootElement);
	}

	public <T> T buildEntityByXML(Class<T> clzz, final Element rootElement) throws OphiuxApiException {
		Reader xmlReader = new Reader() {
			@Override
			public boolean isExistNode(String tagNames) {
				Object value = XMLUtil.getChildElement(rootElement, tagNames);

				return value != null;
			}

			@Override
			public Object getNodeValue(String tagNames) {
				Object value = XMLUtil.getElementValue(rootElement, tagNames);

				return value;
			}

			@Override
			public Object getNodeObject(String tagName, Class<?> subType) throws OphiuxApiException {
				Element childElement = XMLUtil.getChildElement(rootElement, tagName);
				if (childElement != null) {
					return buildEntityByXML(subType, childElement);
				}
				return null;
			}

			@Override
			public List<?> getNodeListObject(String parentName, String tagNames, Class<?> subType)
					throws OphiuxApiException {
				List dataList = new ArrayList<Object>();
				Element parentElement = XMLUtil.getChildElement(rootElement, parentName);
				if (parentElement == null) {
					return null;
				}
				List<Element> currentElementList = XMLUtil.getChildElements(parentElement, tagNames);
				for (Element element : currentElementList) {
					Object obj = XMLUtil.getElementValue(element);
					try {
						if (String.class.isAssignableFrom(subType)) {

						} else if (Long.class.isAssignableFrom(subType)) {

						} else if (Integer.class.isAssignableFrom(subType)) {

						} else if (Boolean.class.isAssignableFrom(subType)) {

						} else if (List.class.isAssignableFrom(subType)) {

						} else {
							obj = buildEntityByXML(subType, element);
						}
						dataList.add(obj);
					} catch (IllegalArgumentException e) {
						e.printStackTrace();
						throw new OphiuxApiException(e);
					}
				}
				return dataList;
			}
		};
		return EntityConverter.convert(clzz, xmlReader);
	}

	public static void main(String[] args) {
		XmlConverter test = new XmlConverter();
	}

	@Override
	public <T> String entityToString(T obj) throws OphiuxApiException {
		return parseEntityToString(obj);
	}

	public <T> String parseEntityToString(T obj) throws OphiuxApiException {
		String targetStr = "";
		Writer writer = new Writer() {

			@Override
			public String writerFromString(Object value, String nodeName) throws OphiuxApiException {
				String str = "";
				if (value == null || value.equals("null")) {
					value = "";
				}
				str += "<" + nodeName + ">" + value + "</" + nodeName + ">";
				return str;
			}

			@Override
			public String writerFromObject(Object obj, String nodeName) throws OphiuxApiException {
				String str = "";
				if (obj != null) {
					String objStr = parseEntityToString(obj);
					str += "<" + nodeName + ">" + objStr + "</" + nodeName + ">";
				} else {
					str += "<" + nodeName + ">" + "" + "</" + nodeName + ">";
				}

				return str;
			}

			@Override
			public <T> String writerFromArray(List<T> valueList, String parentNodeName, String nodeName)
					throws OphiuxApiException {
				String str = "";
				String listStr = "";
				if (valueList != null && valueList.size() != 0) {
					for (T obj : valueList) {
						String objStr = "";
						objStr += "<" + nodeName + ">" + parseEntityToString(obj) + "</" + nodeName + ">";
						listStr += objStr;
					}
				}
				str += "<" + parentNodeName + ">" + listStr + "</" + parentNodeName + ">";
				return str;
			}

		};

		targetStr = EntityConverter.writerToString(obj, writer);
		return targetStr;
	}

	@Override
	public <T> SortedMap entityToMap(T obj) throws OphiuxApiException {
		// TODO Auto-generated method stub
		return null;
	}

}
